package com.itheima.d4_byte_stream;

import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.io.OutputStream;

/**
 * 目标：使用字节流完成对文件的复制操作。
 * IO流的作用？
 * 读写文件数据的
 *
 * I指Input，称为输入流：负责把数据读到内存中去
 * O指Output，称为输出流：负责写数据出去到磁盘等
 *
 *  按流的方向分为：输入流，输出流
 *  按流中数据的最小单位，分为：
 *  字节流--》适合操作所有类型的文件-》比如：音频、视频、图片，文本文件的复制，转移等。
 *  字符流--》只适合操作纯文本文件-》比如：读写txt、java文件等
 *
 *  IO流总体来看就有四大流
 *      字节输入流   抽象类 InputStream     实现类 FileInputStream
 *      字节输出流   抽象类 OutputStream    实现类 FileOutputSteam
 *      字符输入流   抽象类 Reader          实现类 FileReader
 *      字符输出流   抽象类 Writer          实现类 FileWriter
 *
 *总结流的四大类:
 * 字节输入流：以内存为基准，来自磁盘文件/网络中的数据以字节的形式读入到内存中去的流
 * 字节输出流：以内存为基准，把内存中的数据以字节写出到磁盘文件或者网络中去的流。
 * 字符输入流：以内存为基准，来自磁盘文件/网络中的数据以字符的形式读入到内存中去的流。
 * 字符输出流：以内存为基准，把内存中的数据以字符写出到磁盘文件或者网络介质中去的流。
 * */
public class CopyTest5 {
    public static void main(String[] args) throws Exception {
        /*
         * 	任何文件的底层都是字节，字节流做复制，是一字不漏的转移完全部字节，只要复制后的文件格式一致就没问题!
         * 	假设现在需要把D盘的一个图片拷贝到C盘中，首先是在内存中创建字节输入流管道和D盘图片连接，然后再创建字节输出流管道和D盘目标文件连接，指向的目标文件就是用来记住这个图片
         * 	然后在内存中创建一个字节数组，让字节数组从输入流管道read方法读取图片字节数据，读取之后，再通过输出流管道write方法写到D盘目标文件
         *
         *  字节流非常适合做一切文件的复制操作
         * 	任何文件的底层都是字节，字节流做复制，是一字不漏的转移完全部字节，只要复制后的文件格式一致就没问题!
         *  如果是要读取文本文件里面的内容，可以使用后面学习的字符流
         */
        // 需求：复制照片。
        // 1、创建一个字节输入流管道与源文件接通
        InputStream is = new FileInputStream("D:\\Idea\\resource\\图片复制案例\\1.jpg");
        // 2、创建一个字节输出流管道与目标文件接通。    注意要写明需要复制后的文件名称，和write不一样不会自动创建
        OutputStream os = new FileOutputStream("D:\\Idea\\resource\\复制结果.jpg");
        //输出流管道不要加true
        //OutputStream os = new FileOutputStream("D:\\Idea\\resource\\复制结果.jpg",true);

        //除了拷贝图片，也可以拷贝文本文件
        //注意：不会乱码，就算是read读取字节的中途把字节读断了，但是后续继续读过来的字节，会把这些字节连成一个整体
/*
        InputStream is = new FileInputStream("Day08File-Io-App\\src\\itheima03.txt");
        OutputStream os = new FileOutputStream("Day08File-Io-App\\src\\itheima03.txt");
*/


        // 3、创建一个字节数组，负责转移字节数据。
        byte[] buffer = new byte[1024]; // 1KB.
        // 4、从字节输入流中读取字节数据，写出去到字节输出流中。读多少写出去多少。
        //弹幕：兄弟们注意，这里不用加append是因为流里面有个指针，每次下一次循环时，流指针都位于上一次的流尾，相当于直接拼接，加不加append都一样的
        int len; // 记住每次读取了多少个字节。
        while ((len = is.read(buffer)) != -1){
            os.write(buffer, 0, len);
        }

        //一般是后创建的流需要先关掉，先创建的流需要后关掉
        //注意：以后上班代码会有几十上百行，万一上面的代码出现了异常，那么下面流释放资源的代码就没法执行了
        os.close();
        is.close();
        System.out.println("复制完成！！");
    }
}
